﻿// Copyright 2006 - Ricardo Stuven (rstuven@gmail.com)
//
// This file is part of MsSqlSpatial.
// MsSqlSpatial is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// MsSqlSpatial is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public License
// along with MsSqlSpatial; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using GeoAPI.Geometries;
using Microsoft.SqlServer.Server;
using MsSqlSpatial;

public partial class TableValuedFunctions
{
    [SpatialQuery]
    [SqlFunction(
        FillRowMethodName = SpatialQuery.FillRow
        , TableDefinition = SpatialQuery.TableDefinition
        , DataAccess = DataAccessKind.Read
        , SystemDataAccess = SystemDataAccessKind.Read
        )]
    public static IEnumerable RelateQuery(
        SqlString table_name,
        SqlString column_name,
        SqlBytes ewkb,
        SqlString intersectionPattern)
    {
        return SpatialQuery.Execute(table_name, column_name, ewkb, new SpatialQuery.Arguments(intersectionPattern),
                                    RelateQueryHandler);
    }

    [SpatialQuery]
    [SqlFunction(
        FillRowMethodName = SpatialQuery.FillRow
        , TableDefinition = SpatialQuery.TableDefinition
        , DataAccess = DataAccessKind.Read
        , SystemDataAccess = SystemDataAccessKind.Read
        )]
    public static IEnumerable RelateQueryWhere(
        SqlString table_name,
        SqlString column_name,
        SqlBytes ewkb,
        SqlString intersectionPattern,
        SqlString condition)
    {
        return SpatialQuery.Execute(table_name, column_name, ewkb, condition,
                                    new SpatialQuery.Arguments(intersectionPattern), RelateQueryHandler);
    }

    private static IEnumerable RelateQueryHandler(SqlDataReader reader, IGeometry geometry, SpatialQuery.Arguments args)
    {
        string intersectionPattern = args.string1.Value;

        RelateFunction function;
        switch (intersectionPattern.Trim().ToLower())
        {
            case "contains":
                function = geometry.Contains;
                break;
            case "coveredby":
                function = geometry.CoveredBy;
                break;
            case "covers":
                function = geometry.Covers;
                break;
            case "crosses":
                function = geometry.Crosses;
                break;
            case "disjoint":
                function = geometry.Disjoint;
                break;
            case "equals":
                function = geometry.Equals;
                break;
            case "equalsexact":
                function = geometry.EqualsExact;
                break;
            case "intersects":
                function = geometry.Intersects;
                break;
            case "overlaps":
                function = geometry.Overlaps;
                break;
            case "touches":
                function = geometry.Touches;
                break;
            case "within":
                function = geometry.Within;
                break;
            default:
                function = null;
                break;
        }

        var oids = new List<Int64>();
        if (function == null)
            while (reader.Read())
            {
                IGeometry _geometry = ConvertGeometry.ToGeometry(reader.GetSqlBytes(1));
                if (geometry.Relate(_geometry, intersectionPattern))
                {
                    oids.Add((long) reader.GetValue(0));
                }
            }
        else
            while (reader.Read())
            {
                IGeometry _geometry = ConvertGeometry.ToGeometry(reader.GetSqlBytes(1));
                if (function(_geometry))
                {
                    oids.Add((long) reader.GetValue(0));
                }
            }
        return oids;
    }

    #region Nested type: RelateFunction

    private delegate bool RelateFunction(IGeometry g);

    #endregion
} ;